package aries.database;

/******************************************************************************
 * You may modify, publish, and use Aries for your own purpose. BUT
 * DON'T REMOVE THIS TEXT.
 * Visit my facebook: http://www.facebook.com/freeskies or
 * Follow my twitter: @freeskys
 *
 *
 * Author: Harditya Rahmat Ramadhan
 * Licence: GPLv2
 *****************************************************************************/

import aries.utils.ExceptionManager;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class Database {

    /**
     * Oracle database product parameter.
     */
    public static final byte ORACLE = 0;

    /**
     * MySQL database product parameter.
     */
    public static final byte MYSQL = 1;

    /**
     * IBM DB2 database product parameter.
     */
    public static final byte IBM_DB2 = 2;

    /**
     * Access database product parameter.
     */
    public static final byte ACCESS = 3;
    
    /**
     * SQLite database product parameter.
     */
    public static final byte SQLITE = 4;
    
    /**
     * Microsoft SQL Server database product parameter.
     */
    public static final byte MICROSOFT_SQL_SERVER = 5;
    
    /**
     * PointBase Embedded Server database product parameter.
     */
    public static final byte POINTBASE_EMBEDDED_SERVER = 6;
    
    /**
     * Cloudscape database product parameter.
     */
    public static final byte CLOUDSCAPE = 7;
    
    /**
     * Cloudscape RMI database product parameter.
     */
    public static final byte CLOUDSCAPE_RMI = 8;
    
    /**
     * Firebird database product parameter.
     */
    public static final byte FIREBIRD = 9;
    
    /**
     * Microsoft SQL Server JTurbo driver database product parameter.
     */
    public static final byte MICROSOFT_SQL_SERVER_JTURBO = 10;
    
    /**
     * Microsoft SQL Server Sprinta driver database product parameter.
     */
    public static final byte MICROSOFT_SQL_SERVER_Sprinta = 11;
    
    /**
     * Microsoft SQL Server 2000 database product parameter.
     */
    public static final byte MICROSOFT_SQL_SERVER_2000 = 12;
    
    /**
     * PostgreSQL v6.5 and earlier database product parameter.
     */
    public static final byte POSTGRE_SQL_6_5_AND_EARLIER = 13;
    
    /**
     * PostgreSQL v7.0 and later database product parameter.
     */
    public static final byte POSTGRE_SQL_7_AND_LATER = 14;
    
    /**
     * Instant DB v3.13 and earlier database product parameter.
     */
    public static final byte INSTANT_DB_3_13_AND_EARLIER = 15;
    
    /**
     * Instant DB v3.14 and later database product parameter.
     */
    public static final byte INSTANT_DB_3_14_AND_LATER = 16;
    
    /**
     * HypersonicSQL v1.2 and earlier database product parameter.
     */
    public static final byte HYPERSONIC_SQL_1_2_AND_EARLIER = 17;
    
    /**
     * HypersonicSQL v1.3 and later database product parameter.
     */
    public static final byte HYPERSONIC_SQL_1_3_AND_LATER = 18;
    
    /**
     * Your database IP Address.
     */
    private static String ip = "localhost";

    /**
     * Your database port.
     */
    private static String port = "3306";

    /**
     * Your database name.
     */
    private static String dbName = "mysql";

    /**
     * Username to gain access to your database.
     */
    private static String user = "root";

    /**
     * Password to gain access to your database.
     */
    private static String pass = "";

    /**
     * Your database product. Default is MySQL.
     */
    private static byte product = Database.MYSQL;

    /**
     * Connection.
     */
    private static Connection conn = null;

    /**
     * Statement.
     */
    private static Statement stat = null;

    /**
     * Set wether Alib need to show SQL on command line or not.
     */
    private static int showSQL = 0;

    /**
     * Set wether Alib need to automatically open and close connection.
     */
    private static Boolean automatic = true;

    /**
     * Show SQL.
     */
    public static final int SHOW_SQL = 1;

    /**
     * Hide SQL.
     */
    public static final int HIDE_SQL = 0;
    
    /**
     * Filename for SQLite database management system.
     */
    public static String fileName = "";

    /**
     * Get ip value.
     *
     * @return ip
     */
    public static String getIp() {
        return ip;
    }

    /**
     * Set ip value.
     *
     * @param ip
     */
    public static void setIp(String ip) {
        Database.ip = ip;
    }

    /**
     * Get port value.
     *
     * @return port
     */
    public static String getPort() {
        return port;
    }

    /**
     * Set port value.
     *
     * @param port
     */
    public static void setPort(String port) {
        Database.port = port;
    }

    /**
     * Get database name value.
     *
     * @return database name
     */
    public static String getDbName() {
        return dbName;
    }

    /**
     * Set database name value.
     *
     * @param dbName
     */
    public static void setDbName(String dbName) {
        Database.dbName = dbName;
    }

    /**
     * Get username value.
     *
     * @return username
     */
    public static String getUser() {
        return user;
    }

    /**
     * Set username value.
     *
     * @param user
     */
    public static void setUser(String user) {
        Database.user = user;
    }

    /**
     * Get password value.
     *
     * @return password
     */
    public static String getPass() {
        return pass;
    }

    /**
     * Set password value.
     *
     * @param pass
     */
    public static void setPass(String pass) {
        Database.pass = pass;
    }

    /**
     * Get database product value.
     *
     * @return database product
     */
    public static byte getProduct() {
        return product;
    }

    /**
     * Set database product value.
     *
     * @param product
     */
    public static void setProduct(byte product) {
        Database.product = product;
    }

    /**
     * Get connection value.
     *
     * @return connection
     */
    public static Connection getConn() {
        return conn;
    }

    /**
     * Set connection value.
     *
     * @param conn
     */
    public static void setConn(Connection conn) {
        Database.conn = conn;
    }

    /**
     * Get statement value.
     *
     * @return statement
     */
    public static Statement getStat() {
        return stat;
    }

    /**
     * Set statement value.
     *
     * @param stat
     */
    public static void setStat(Statement stat) {
        Database.stat = stat;
    }

    /**
     * Get show sql value.
     *
     * @return show sql
     */
    public static int getShowSQL() {
        return showSQL;
    }

    /**
     * Set show sql value.
     *
     * @param showSQL
     * @deprecated Changed to setShowSQL(Boolean showSQL)
     */
    public static void setShowSQL(int showSQL) {
        Database.showSQL = showSQL;
    }
    
    /**
     * Set show sql value.
     * 
     * @param showSQL 
     */
    public static void setShowSQL(Boolean showSQL) {
        if (showSQL) 
            Database.showSQL = Database.SHOW_SQL;
        else
            Database.showSQL = Database.HIDE_SQL;
    }

    /**
     * Get automatic value.
     *
     * @return automatic
     */
    public static Boolean getAutomatic() {
        return automatic;
    }

    /**
     * Set automatic value.
     *
     * @param automatic
     */
    public static void setAutomatic(Boolean automatic) {
        Database.automatic = automatic;
    }

    /**
     * Get filename value.
     * 
     * @return filename
     */
    public static String getFileName() {
        return fileName;
    }

    /**
     * Set filename value.
     * 
     * @param fileName 
     */
    public static void setFileName(String fileName) {
        Database.fileName = fileName;
    }

    /**
     * Get specified className.
     *
     * @return className
     */
    public static String getClassName() {
        return getClassName(Database.getProduct());
    }

    /**
     * Get specified className.
     *
     * @param databaseProduct
     * @return className
     */
    public static String getClassName(int databaseProduct) {
        String className = "";
        switch (databaseProduct) {
            case 0: className = "oracle.jdbc.driver.OracleDriver"; break;
            case 1: className = "com.mysql.jdbc.Driver"; break;
            case 2: className = "COM.ibm.db2.jdbc.app.DB2Driver"; break;
            case 3: className = "sun.jdbc.odbc.JdbcOdbcDriver"; break;
            case 4: className = "org.sqlite.JDBC"; break;
            case 5: className = "weblogic.jdbc.mssqlserver4.Driver"; break;
            case 6: className = "com.pointbase.jdbc.jdbcUniversalDriver"; break;
            case 7: className = "COM.cloudscape.core.JDBCDriver"; break;
            case 8: className = "RmiJdbc.RJDriver"; break;
            case 9: className = "org.firebirdsql.jdbc.FBDriver"; break;
            case 10: className = "com.ashna.jturbo.driver.Driver"; break;
            case 11: className = "com.inet.tds.TdsDriver"; break;
            case 12: className = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; break;
            case 13: className = "postgresql.Driver"; break;
            case 14: className = "org.postgresql.Driver"; break;
            case 15: className = "jdbc.idbDriver"; break;
            case 16: className = "org.enhydra.instantdb.jdbc.idbDriver"; break;
            case 17: className = "hSql.hDriver"; break;
            case 18: className = "org.hsql.jdbcDriver"; break;
        }
        return className;
    }

    /**
     * Get URL to intialize JDBC connection.
     *
     * @return url
     */
    public static String getURL() {
        return getURL(Database.getProduct());
    }

    /**
     * Get URL to initialize JDBC connection.
     *
     * @param databaseProduct
     * @return url
     */
    public static String getURL(int databaseProduct) {
        String url = "";
        switch (databaseProduct) {
            case 0: url = "jdbc:oracle:thin:@"+Database.getIp()+":"+Database.getPort()+":XE"; break;
            case 1: url = "jdbc:mysql://"+Database.getIp()+":"+Database.getPort()+"/"+Database.getDbName(); break;
            case 2: url = "jdbc:db2://"+Database.getIp()+":"+Database.getPort()+"/"+Database.getDbName(); break;
            case 3: url = "jdbc:odbc:"+Database.getDbName(); break;
            case 4: url = "jdbc:sqlite:/"+Database.getFileName(); break;
            case 5: url = "jdbc:weblogic:mssqlserver4:"+Database.getDbName()+"@"+Database.getIp()+":"+Database.getPort(); break;
            case 6: url = "jdbc:pointbase://embedded[:"+Database.getPort()+"]/"+Database.getDbName(); break;
            case 7: url = "jdbc:cloudscape:"+Database.getDbName(); break;
            case 8: url = "jdbc:rmi://"+Database.getIp()+":"+Database.getPort()+"/jdbc:cloudscape:"+Database.getDbName(); break;
            case 9: url = "jdbc:firebirdsql:[//"+Database.getIp()+"[:"+Database.getPort()+"]/]"+Database.getDbName(); break;
            case 10: url = "jdbc:JTurbo://"+Database.getIp()+":"+Database.getPort()+"/"+Database.getDbName(); break;
            case 11: url = "jdbc:inetdae:"+Database.getIp()+":"+Database.getPort()+"?database="+Database.getDbName(); break;
            case 12: url = "jdbc:microsoft:sqlserver://"+Database.getIp()+":"+Database.getPort()+"[;DatabaseName="+Database.getDbName()+"]"; break;
            case 13: url = "jdbc:postgresql://"+Database.getIp()+":"+Database.getPort()+"/"+Database.getDbName(); break;
            case 14: url = "jdbc:postgresql://"+Database.getIp()+":"+Database.getPort()+"/"+Database.getDbName(); break;
            case 15: url = "jdbc:idb:"+Database.getDbName(); break;
            case 16: url = "jdbc:idb:"+Database.getDbName(); break;
            case 17: url = "jdbc:HypersonicSQL:"+Database.getDbName(); break;
            case 18: url = "jdbc:HypersonicSQL:"+Database.getDbName(); break;
        }
        return url;
    }

    /**
     * Open connection to the database.
     *
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public static void open() throws ClassNotFoundException, SQLException {
        Class.forName(getClassName());
        setConn(DriverManager.getConnection(getURL() ,getUser(), getPass()));
        setStat(getConn().createStatement());
    }

    /**
     * Close connection to the database.
     *
     * @throws SQLException
     */
    public static void close() throws SQLException {
        if (getStat() != null) getStat().close();
        if (getConn() != null) getConn().close();
    }
    
    /**
     * Reset connection to the database.
     * 
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public static void reset() throws SQLException, ClassNotFoundException {
        close();
        open();
    }
    
    /**
     * Test a connection to the database.
     * 
     * @return Boolean
     * @throws ClassNotFoundException 
     */
    public static Boolean test() throws ClassNotFoundException {
        Boolean result = true;
        try {
            open();
        } catch (SQLException e) {
            if (e.getErrorCode() == ExceptionManager.MYSQL_DOESNT_START) {
                result = false;
            }
        }
        return result;
    }
    
    /**
     * Create database from database configuration.
     * 
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public static void create() throws SQLException, ClassNotFoundException {
        Query.createDatabase();
    }
    
    /**
     * Drop the current database.
     * 
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public static void drop() throws SQLException, ClassNotFoundException {
        Query.dropDatabase(dbName);
    }

}